package com.yangyang.ralearn.server;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.yangyang.ralearn.client.rlclient.Ralearn;
import com.yangyang.ralearn.common.Constants;
import com.yangyang.ralearn.common.framework.BeanManager;
import com.yangyang.ralearn.net.frame.FrameDecoder;
import com.yangyang.ralearn.net.load.ILoad;
import com.yangyang.ralearn.net.message.AbstractMessage;
import com.yangyang.ralearn.server.ServerManager;

public class ServerSimulatorHandler extends SimpleChannelHandler {

	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
			throws Exception {
		// TODO Auto-generated method stub
		AbstractMessage message = (AbstractMessage) e.getMessage();
		if (message != null) {
			int id = message.getId() % Constants.MESSAGEBASE;
			try {
				message.Do(id / 10, id % 10, ctx.getChannel());
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
		// TODO Auto-generated method stub
		Logger.getLogger(ServerSimulatorHandler.class).debug(e);
	}

	@Override
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		// TODO Auto-generated method stub
		Logger.getLogger(ServerSimulatorHandler.class).debug("welcome...");
		super.channelConnected(ctx, e);
	}

	@Override
	public void channelDisconnected(ChannelHandlerContext ctx,
			ChannelStateEvent e) throws Exception {
		// TODO Auto-generated method stub
		super.channelDisconnected(ctx, e);
		Logger.getLogger(ServerSimulatorHandler.class).debug("bye...");
		ServerManager.instance().removeChannel(e.getChannel().getId());
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ApplicationContext context = BeanManager.getApplicationContext();

		Map<String, ILoad> assembles = context.getBeansOfType(ILoad.class);
		for (Entry<String, ILoad> entry : assembles.entrySet()) {
			Logger.getLogger(Ralearn.class).info("loading:" + entry.getKey());
			entry.getValue().onLoad(context);
		}

		ChannelFactory factory = new NioServerSocketChannelFactory(
				Executors.newCachedThreadPool(),
				Executors.newCachedThreadPool());
		ServerBootstrap bootstrap = new ServerBootstrap(factory);
		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			public ChannelPipeline getPipeline() {
				return Channels.pipeline(new FrameDecoder(),
						new ServerSimulatorHandler());
			}
		});
		bootstrap.setOption("child.tcpNoDelay", true);
		bootstrap.setOption("child.keepAlive", true);
		bootstrap.bind(new InetSocketAddress(8080));

	}

}
